package com.webshooter.systems;

import com.webshooter.ClientUpdater;
import com.webshooter.ShooterEndpoint;
import com.webshooter.decoder.KeyPressCommand;
import com.webshooter.decoder.KeyUpCommand;
import com.webshooter.decoder.UpdatePlayerAngleCommand;
import com.webshooter.encoder.UpdateEntityEvent;
import com.webshooter.math.Vector;
import com.webshooter.entity.Entity;
import com.webshooter.entity.EntityContainer;

import com.webshooter.map.TileMap;
import javax.ejb.Singleton;
import javax.ejb.Startup;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.Timeout;
import javax.ejb.TimerConfig;
import javax.ejb.TimerService;
import javax.inject.Inject;

@Startup
@Singleton
public class MovementSystem {

    @Inject
    private ClientUpdater clientUpdater;
    @Inject
    private EntityContainer entityContainer;
    @Inject
    private TileMap tileMap;
    @Resource
    TimerService tservice;
    private final long updateInterval = 50;
    private final float speedPixelPerSec = 100;
    private final float pixelsPerUpdate = speedPixelPerSec * ((float) updateInterval / 1000);

    @PostConstruct
    public void init() {
        tservice.createIntervalTimer(updateInterval, updateInterval, new TimerConfig());
    }

    @Timeout
    public void timeout() throws InterruptedException {
        for (Entity entity : entityContainer.getAllEntities()) {
            update(entity);
        }
    }

    public void update(Entity entity) {
        if (entity.gameLogicState == Entity.GameLogicState.ALIVE) {
            entity.deadTime = 0;
            entity.pos = tileMap.calcCollisionCorrectedPosition(entity.pos, getMovementVector(entity));
        }
        clientUpdater.addEvent(new UpdateEntityEvent(entity));
    }

    public void keyPress(KeyPressCommand command) {
        Entity entity = entityContainer.findEntityByName(command.getName());
        if (entity == null) {
            return;
        }
        switch (command.getKeyCode()) {
            case "STRAFE_LEFT":
                entity.strafeLeft = true;
                break;
            case "MOVE_FORWARD":
                entity.moveForward = true;
                break;
            case "STRAFE_RIGHT":
                entity.strafeRight = true;
                break;
            case "MOVE_BACKWARD":
                entity.moveBackward = true;
                break;
        }
    }

    public void keyUp(KeyUpCommand command) {
        Entity entity = entityContainer.findEntityByName(command.getName());
        if (entity == null) {
            return;
        }
        switch (command.getKeyCode()) {
            case "STRAFE_LEFT":
                entity.strafeLeft = false;
                break;
            case "MOVE_FORWARD":
                entity.moveForward = false;
                break;
            case "STRAFE_RIGHT":
                entity.strafeRight = false;
                break;
            case "MOVE_BACKWARD":
                entity.moveBackward = false;
                break;
        }
    }

    public void updatePlayerAngle(UpdatePlayerAngleCommand command) {
        Entity entity = entityContainer.findEntityByName(command.getName());
        if (entity == null) {
            return;
        }

        entity.angle = command.getAngle();
    }

    private Vector getMovementVector(Entity entity) {
        Vector movementVector = new Vector();
        if (entity.strafeLeft) {
            movementVector.x -= pixelsPerUpdate;
        }
        if (entity.moveForward) {
            movementVector.y -= pixelsPerUpdate;
        }
        if (entity.strafeRight) {
            movementVector.x += pixelsPerUpdate;
        }
        if (entity.moveBackward) {
            movementVector.y += pixelsPerUpdate;
        }
        return movementVector.normalizeTo(pixelsPerUpdate);
    }
}
